import { NGXLogger } from 'ngx-logger';
import { Participant } from './../entity/TT';
import { Injectable, EventEmitter } from '@angular/core';
import {User, AuthUser, OPosition, OSize, BookedWrapper, Booked, Participants} from '../entity/TT';

import { Message } from '../entity/Chat';
import { TrackWrapper, CONNECTION_STATUS, TrackType } from '../entity/ORTC';
import { PainterEvent } from '../entity/ToolItem';
import { OfflineService } from './offline.service';
import { Utils } from '../common/Common';


export enum EventSource {
  CURSOR = 'CURSOR',
  CHAT = 'CHAT',
  XMPP_MESSAGE = 'XMPP_MESSAGE',
  XMPP_CONNECTION_STATUS = 'XMPP_CONNECTION_STATUS',
  MESSAGE = 'MESSAGE',
  RECORD_CALENDAR = 'RECORD_CALENDAR',
  SCHEDULE_CALENDAR = 'SCHEDULE_CALENDAR',
  ToolItem = 'ToolItem',
  TOOL_COLOR = 'TOOL_COLOR',
  TOOL_SIZE = 'TOOL_SIZE',
  LOCAL_TRACK = 'LOCAL_TRACK',
  REMOTE_TRACK = 'REMOTE_TRACK',
  USER_LEFT = 'USER_LEFT',
  USER_JOINED = 'USER_JOINED',
  SELECT_ALL = "SELECT_ALL",
  MUTE = "MUTE",
  MUTE_CHANGED = "MUTE_CHANGED",
  MUTE_VIDEO = 'MUTE_VIDEO',
  LOGIN = "LOGIN",
  CONTROLLER_VOICE = "CONTROLLER_VOICE",
  CONTROLLER_WHITE_BOARD = "CONTROLLER_WHITE_BOARD",
  PAINT = "PAINT",
  PAINT_CHANGED = "PAINT_CHANGED",
  WHITE_BOARD_CHANGED = "WHITE_BOARD_CHANGED",
  GIFT_COIN = "GIFT_COIN",
  GIFT_FABULOUS = "GIFT_FABULOUS",
  GIFT_CHANGED = 'GIFT_CHANGED',
  EXIT = "EXIT",
  UNLOAD='UNLOAD',
  TOGGLE_TOOLBOX = "TOGGLE_TOOLBOX",
  TOGGLE_TOOLBOX_CHANGED = "TOGGLE_TOOLBOX_CHANGED",
  BOOKED = "BOOKED",
  PARTICIPANT_GO_HOME = "PARTICIPANT_GO_HOME",
  PARTICIPANT_SELECT = "PARTICIPANT_SELECT",
  PARTICIPANT_SELECTED = "PARTICIPANT_SELECTED",
  PARTICIPANT_MOVE = "PARTICIPANT_MOVE",
  PARTICIPANT_MOVED = "PARTICIPANT_MOVED",
  PARTICIPANT_SIZE = "PARTICIPANT_SIZE",
  PARTICIPANT_SIZE_CHANGED = "PARTICIPANT_SIZE_CHANGED",
  PARTICIPANT_GO_HOMEED = "PARTICIPANT_GO_HOMEED",
  ERROR = "ERROR",
  CLOCK_TICK = "CLOCK_TICK",
  RESIZE_CHAT_VIEWPORT = 'RESIZE_CHAT_VIEWPORT',
  SET_VOICE_VALUE = 'SET_VOICE_VALUE',
  SET_CHANGED = "SET_CHANGED",
  SET_THEME_VALUE = "SET_THEME_VALUE",

  CONFERENCE_LIST = 'CONFERENCE_LIST',
  TRACK_CHANGED='TRACK_CHANGED',
  TRACK_PLAYED='TRACK_PLAYED',
  REGISTER_EVENT = 'REGISTER_EVENT',

}


export class EventMessage {
  source : EventSource;
  data   : any;
}

export class ParticipantMoveEvent extends Participant  {
  position: OPosition;
}

export class ParticipantSizeEvent extends Participant  {
  size: OSize;
}

export class ParticipantSelectEvent extends Participants {
  select:boolean;
}

export class ParticipantGoHomeEvent extends Participant {
  active:boolean;
}

export class ParticipantMuteChangeEvent extends Participant {
  active:boolean;
}

export class ParticipantPlayEvent extends Participant {
  trackType: TrackType
}

@Injectable({
  providedIn: 'root'
})
export class EventService {



  toggledChat : boolean = false
  recordSelectedDay : any
  sechuleSelectedDay : any
  booked: Booked

  public emit: any;

  private timer: any = null;
  private ticks: number = null;
  private TICK_TIME : number = 1000;  //clock tick times

  constructor(
    private log: NGXLogger,
    private offlineService: OfflineService,
  ) {
    // 定义发射事件
     this.emit = new EventEmitter();

    //  timer
     clearInterval(this.timer);
     this.timer = setInterval(()=>{
       this.ticks += 1;
       this.sendEvent(EventSource.CLOCK_TICK, this.ticks);
     }, this.TICK_TIME);

     this.subscribeEvent((evt: EventMessage)=>{
      switch (evt.source) {
        case EventSource.BOOKED:{
          const bookedWrapper: BookedWrapper = evt.data
          const current : Booked = bookedWrapper.current;
          if (current) {
            this.booked = current;
            setTimeout(()=>{
                this.offlineService.restoringDraw(this.booked.sn, (item: PainterEvent) => {
                    this.log.debug("restoring", item)
                    this.sendPaintChange(item);
                });
              }, 1200)
          }
          break;
        }
      }
    });
  }

  sendConferenceList(list: Booked[]) {
    let evt : EventMessage = { source : EventSource.CONFERENCE_LIST, data : list}
    this.emit.emit(evt);
  }

  sendEvent( src: EventSource, msg: any ) {
    let evt : EventMessage = { source : src, data : msg}
    this.emit.emit(evt);
  }

  subscribeEvent(func: (arg0: any)=>void) {
    this.emit.subscribe((evt: EventMessage) => {
      func(evt);
    })
  }

  sendError(msg: any){
    this.emit.emit({source: EventSource.ERROR, data: msg});
  }

  subscribeClockTick(func: (ticks: number) => void) {
    this.emit.subscribe((evt: EventMessage) => {
      if(evt.source == EventSource.CLOCK_TICK)
        func(evt.data);
    })
  }

  sendDraw(msg: PainterEvent){
    let evt : EventMessage = { source : EventSource.PAINT, data : msg}
    this.emit.emit(evt);

    let k : string = Utils.nowTime()+'';

    if(this.booked){
      this.offlineService.setDrawItem(this.booked.sn, k, msg);
    }
  }

  subscribeDraw(func: (arg0: PainterEvent)=>void) {
    this.emit.subscribe((evt: EventMessage) => {
      if(evt.source == EventSource.PAINT)
        func(evt.data);
    })
  }

  sendPaintChange(msg: any){
    let evt : EventMessage = { source : EventSource.PAINT_CHANGED, data : msg}
    this.emit.emit(evt);
  }

  subscribePaintChange(func: (arg0: any)=>void) {
    this.emit.subscribe((evt: EventMessage) => {
      if(evt.source == EventSource.PAINT_CHANGED)
        func(evt.data);
    })
  }

  sendToggle( src: EventSource, toggle: boolean ) {
    switch(src){
      case EventSource.CHAT:
        this.toggledChat = toggle;
      break;
    }
  }

  sendXMPPMessage(msg: any){
    let evt : EventMessage = { source : EventSource.XMPP_MESSAGE, data : msg}
    this.emit.emit(evt);
  }

  sendXMPPConnectionStatus(status: any){
    let evt : EventMessage = {source: EventSource.XMPP_CONNECTION_STATUS, data: status}
    this.emit.emit(evt)
  }


  subscribeLocalTrack(func: (arg0: any)=>void) {
    this.emit.subscribe((evt: EventMessage) => {
      switch(evt.source){
        case EventSource.LOCAL_TRACK:
          func(evt.data);
          break;
      }
    })
  }

  subscribeRemoteTrack(func: (arg0: any)=>void) {
    this.emit.subscribe((evt: EventMessage) => {
      switch(evt.source){
        case EventSource.REMOTE_TRACK:
          func(evt.data);
          break;
      }
    })
  }

  subscribeUserLeft(func: (arg0: any)=>void) {
    this.emit.subscribe((evt: EventMessage) => {
      switch(evt.source){
        case EventSource.USER_LEFT:
          func(evt.data);
          break;
      }
    })
  }

  sendLogin(msg: User){
    let evt : EventMessage = { source : EventSource.LOGIN, data : msg}
    this.emit.emit(evt);
  }

  subscribeLogin(func: (arg0: User)=>void){
    this.emit.subscribe((evt: EventMessage) => {
      switch(evt.source){
        case EventSource.LOGIN:
          func(evt.data);
          break;
      }
    })
  }

  subscribeSelectAll(func: (arg0: boolean)=>void) {
    this.emit.subscribe((evt: EventMessage) => {
      switch(evt.source){
        case EventSource.SELECT_ALL:
          func(evt.data);
          break;
      }
    })
  }

  subscribeXMPPConnectionStatus(func: Function){
    this.emit.subscribe((evt: EventMessage) => {
      switch(evt.source){
        case EventSource.XMPP_CONNECTION_STATUS:
        func(evt.data);
        break;
      }
    })
  }

  sendMessage(msg: any){
    let evt : EventMessage = {source : EventSource.MESSAGE, data:msg}
    this.emit.emit(evt)
  }

  sendEventMessage(em: EventMessage){
    this.emit.emit(em)
  }

  sendLocalTrack(msg: any){
    this.emit.emit({source : EventSource.LOCAL_TRACK, data:msg})
  }

  sendRemoteTrack(msg: TrackWrapper){
    this.emit.emit({source : EventSource.REMOTE_TRACK, data:msg})
  }

  sendUserLeft(msg: any) {
    this.emit.emit({source : EventSource.USER_LEFT, data:msg})
  }

  sendSelectAll(msg: boolean){
    this.emit.emit({source : EventSource.SELECT_ALL, data:msg})
  }

  sendMute(msg: boolean){
    this.emit.emit({source : EventSource.MUTE, data:msg})
  }

  subscribeMute(func: (arg0: boolean)=>void) {
    this.emit.subscribe((evt: EventMessage) => {
      switch(evt.source){
        case EventSource.MUTE:
          func(evt.data);
          break;
      }
    })
  }

  sendWhiteBoard(msg: boolean){
    this.emit.emit({source : EventSource.CONTROLLER_WHITE_BOARD, data:msg})
  }

  subscribeWhiteBoard(func: (arg0: boolean)=>void) {
    this.emit.subscribe((evt: EventMessage) => {
      switch(evt.source){
        case EventSource.CONTROLLER_WHITE_BOARD:
          func(evt.data);
          break;
      }
    })
  }

  sendWhiteBoardChanged(msg: any){
    this.emit.emit({source : EventSource.WHITE_BOARD_CHANGED, data:msg})
  }

  sendGiftChanged(msg: any){
    this.emit.emit({source : EventSource.GIFT_CHANGED, data:msg})
  }

  subscribeGiftChanged(func: (arg0: any)=>void) {
    this.emit.subscribe((evt: EventMessage) => {
      switch(evt.source){
        case EventSource.GIFT_CHANGED:
          func(evt.data);
          break;
      }
    })
  }

  subscribeWhiteBoardChanged(func: (arg0: any)=>void) {
    this.emit.subscribe((evt: EventMessage) => {
      switch(evt.source){
        case EventSource.WHITE_BOARD_CHANGED:
          func(evt.data);
          break;
      }
    })
  }

  sendGiftCoin(msg: any){
    this.emit.emit({source : EventSource.GIFT_COIN, data:msg})
  }

  sendGiftFabulous(msg: any) {
    this.emit.emit({source : EventSource.GIFT_FABULOUS, data:msg})
  }

  subscribeGiftCoin(func: (arg0: any)=>void) {
    this.emit.subscribe((evt: EventMessage) => {
      switch(evt.source) {
        case EventSource.GIFT_COIN:
          func(evt.data);
          break;
      }
    })
  }

  sendMuteChanged(msg: ParticipantMuteChangeEvent){
    this.emit.emit({source : EventSource.MUTE_CHANGED, data:msg})
  }

  subscribeMuteChanged(func: (arg0: ParticipantMuteChangeEvent)=>void) {
    this.emit.subscribe((evt: EventMessage) => {
      switch(evt.source){
        case EventSource.MUTE_CHANGED:
          func(evt.data);
          break;
      }
    })
  }



  subscribeToolItem(func: Function){
    this.emit.subscribe((evt: EventMessage) => {
      switch(evt.source){
        case EventSource.ToolItem:
        func(evt.data);
        break;
      }
    })
  }

  subscribeToolColor(func: Function){
    this.emit.subscribe((evt: EventMessage) => {
      switch(evt.source){
        case EventSource.TOOL_COLOR:
        func(evt.data);
        break;
      }
    })
  }

  subscribeToolSize(func: Function){
    this.emit.subscribe((evt: EventMessage) => {
      switch(evt.source){
        case EventSource.TOOL_SIZE:
        func(evt.data);
        break;
      }
    })
  }

  subscribeMessage(func : Function) {
    this.emit.subscribe((evt: EventMessage) => {
      switch(evt.source){
        case EventSource.MESSAGE:
        func(evt.data);
        break;
      }
    })
  }

  sendExit() {
    this.emit.emit({source : EventSource.EXIT, data:true})
  }

  subscribeExit(func : Function) {
    this.emit.subscribe((evt: EventMessage) => {
      switch(evt.source){
        case EventSource.EXIT:
        func(evt.data);
        break;
      }
    })
  }

}

